<?php
	
	/**
	 * Verifies bootstrapper execution to ensure file
	 * necessities, and disabling direct access
	 */
	defined('ENGINE') or exit;
	
	/**
	 * Module management class;  Manage the loading, information
	 * and permissions associated with every module
	 */
	final class Modules
	{
		/**
		 * Private instance to the Engine registry
		 */
		protected $engine;
		
		/**
		 * Holds an array of all datatables currently on
		 * the site
		 */
		protected $datatables;
		
		/**
		 * Holds an array of all modules currently installed
		 */
		protected $modules;
		
		/**
		 * Constructor, instanciates the use of the modular system.
		 * Detecting currently installed modules, and their settings.
		 */
		public function __construct()
		{
			$this->engine = Engine::init();
			
			if($this->engine->db === false || $this->engine->cache === false)
			{
				throw new Engine_Basic_Exception('A database driver must be initialized with the caching object constructed alongside it to construct the Modular system');
			}
			
			foreach($this->engine->cache->modules as $key => $module)
			{
				$this->modules[$module] = $module;
				
				if(!$this->load($module))
				{
					throw new Engine_Basic_Exception('An unknown error has occured while initializing the module <code>%s</code>', $module);
				}
			}
		}
		
		/**
		 * Determines if a module has been installed in the system
		 */
		public function is_installed($module = NULL)
		{
			if($module != NULL && isset($this->modules[$module]))
			{
				return(true);
			}
			
			return(false);
		}
		
		/**
		 * Loads a module into the registry as well as verify
		 * its validities.
		 */
		protected function load($module, $prefix = 'module_', $directory = NULL, $construct = 'construct.php')
		{
			$class_name	= $prefix . $module;
			$directory	= ((is_null($directory)) ? MODULES_DIR . DIRECTORY_SEPARATOR . strtolower($module) : $directory);
			$construct	= $directory . DIRECTORY_SEPARATOR . $construct;
			
			$database	= $directory . DIRECTORY_SEPARATOR . 'database';
			
			if(!is_dir($directory))
			{
				throw new Engine_Basic_Exception('Unable to initialize the module %s as the resource folder no longer exists', $module);
			}
			
			if(!file_exists($construct))
			{
				throw new Engine_Basic_Exception('Unable to initialize the module %s as no construct file exists no longer exists', $module);
			}
			
			require_once($construct);
			
			if(!class_exists($class_name))
			{
				throw new Engine_Basic_Exception('Unable to initialize the module %s as the construct incorrectly uses the API and does not define the object %s', $module, $class_name);
			}
			
			if(is_object($module))
			{
				throw new Engine_Basic_Exception('Unable to initialize the module %s as there is an object name duplication for the class %s', $module);
			}
			
			/**
			 * Automatically install database tables
			 * for modules that have been installed if
			 * they don't exist
			 */
			if(is_dir($database))
			{
				foreach(glob($database . DIRECTORY_SEPARATOR . '*') as $filename)
				{
					$file = str_replace($database . DIRECTORY_SEPARATOR, '', $filename);
					$extension = substr(strrchr($filename, '.'), 1);
					$table = str_replace('.' . $extension, '', $file);
					
					if($extension == 'sql' && !$this->engine->db->table_exists($table))
					{
						$sql = file_get_contents($filename);
						$this->engine->db->multi_query($sql);
						
						if(file_exists($database . DIRECTORY_SEPARATOR . $file . '.backup'))
						{
							$sql = file_get_contents($database . DIRECTORY_SEPARATOR . $file . '.backup');
							$this->engine->db->multi_query($sql);
						}
					}
				}
			}
			
			$this->engine->register(strtolower($module), $class_name);
			
			if(isset($this->{$module}))
			{
				throw new Engine_Basic_Exception('Unable to initialize the module %s as the variable used to store the object in the modules register is already in use', $module);
			}
			
			return($this->{$module} = $module);
		}
	}

?>